package cm.com.blackboard.DataModule4B2.customizeConfigUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import blackboard.persist.PersistenceException;
import blackboard.platform.context.ContextManager;
import blackboard.platform.context.ContextManagerFactory;
import blackboard.platform.context.UnsetContextException;
import blackboard.platform.vxi.data.VirtualInstallation;
import blackboard.platform.vxi.service.VirtualSystemException;
import cn.com.blackboard.DataModule4B2.util.HierarchicalQueryModel;
import cn.com.blackboard.DataModule4B2.util.MyBatisXMLModel;

public class HierarchicalQueryLoader {

	private static final Logger logger = LoggerFactory.getLogger(HierarchicalQueryLoader.class);
	
	//static String profilepath=HierarchicalQueryLoader.class.getClassLoader().getResource("/HierarchicalQueryConfig.xml").getPath();
	static String profilepath = System.getProperty("user.dir")+"/target/classes/HierarchicalQueryConfig.xml";
	
	final static String oracleAppender = "||";
	final static String mssqlAppender = "+";
	
	private static List<HierarchicalQueryModel> list = new ArrayList<HierarchicalQueryModel>();
    static { 
    	try {
			parseXML();
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    private static void parseXML() throws JDOMException, IOException{   	
    	String docStr = URLDecoder.decode(profilepath, "utf-8");
    	SAXBuilder builder=new SAXBuilder(false);
    	Document doc=builder.build(docStr);
    	Element hierarchicalQueryModels=doc.getRootElement();
    	List hqModelList=hierarchicalQueryModels.getChildren("HierarchicalQueryModel");
    	for(Iterator iter = hqModelList.iterator(); iter.hasNext();){   	
    		HierarchicalQueryModel hierarchicalQueryModel = new HierarchicalQueryModel();
    		Element hierarchicalQueryModelEle = (Element) iter.next();
    		if(Boolean.parseBoolean(hierarchicalQueryModelEle.getAttribute("on").getValue())){
    			hierarchicalQueryModel.setMainTable(hierarchicalQueryModelEle.getChildTextTrim("mainTable"));
    			hierarchicalQueryModel.setSubTable(hierarchicalQueryModelEle.getChildTextTrim("subTable"));
    			hierarchicalQueryModel.setSplitor(hierarchicalQueryModelEle.getChildTextTrim("splitor"));
    			hierarchicalQueryModel.setOnCondition(hierarchicalQueryModelEle.getChildTextTrim("onCondition"));
    			hierarchicalQueryModel.setTargetAttribute(hierarchicalQueryModelEle.getChildTextTrim("targetAttribute"));
    			List<Element> saList = hierarchicalQueryModelEle.getChild("sourceAttributes").getChildren("sourceAttribute");
    			List<String> sourceAttributeList = new ArrayList<String>(); 			
    			for(int i = 0; i < saList.size(); i++){
    				String sa = saList.get(i).getText();
    				sourceAttributeList.add(sa);
    			}
    			hierarchicalQueryModel.setSourceAttributes(sourceAttributeList);
    			list.add(hierarchicalQueryModel);
    		}
    	}
    }	
    
    private static HashMap<String,String> entryTableMap = new HashMap<String,String>();
    static{
    	entryTableMap.put("CourseInfo", "BB_COURSE_INFO");
    	entryTableMap.put("TeacherCourseInfo", "BB_TEACHER_COURSE");
    }

    private static HashMap<String,String> attrColMap = new HashMap<String,String>();
    static{
    	attrColMap.put("courseId", "COURSE_ID");
    	attrColMap.put("courseName", "COURSE_NAME");
    	attrColMap.put("userId", "USER_ID");
    	attrColMap.put("departmentId", "DEPARTMENT_ID");
    }
    
	public static List<HierarchicalQueryModel> getHierarchicalQueryModelList() {
		return list;
	}
	
	public static String getDBType(){
		ContextManager cm = ContextManagerFactory.getInstance();
    	VirtualInstallation vi = null;
    	try {
			vi = cm.getContext().getVirtualInstallation();
		} catch (VirtualSystemException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (PersistenceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsetContextException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
		String dbType = vi.getDbType();
		return dbType;
	}
	
	public static boolean isHierarchicalQuery(Class cls){
		if(list.isEmpty())
			return false;
		for(HierarchicalQueryModel model:list){
			if(model.getMainTable().equalsIgnoreCase(cls.getSimpleName()))
				return true;
		}
		return false;
	}
	
	public static MyBatisXMLModel getMyBatisXMLModelByClsName(Class cls){
		MyBatisXMLModel myBatisXMLModel = new MyBatisXMLModel();
		HierarchicalQueryModel targetModel = null;
		for(HierarchicalQueryModel model:list){
			if(model.getMainTable().equalsIgnoreCase(cls.getSimpleName()))
				targetModel = model;
		}
		if(targetModel==null){
			logger.info("can't find related HierarchicalQuery in configuration files");
			return null;
		}
		String mainEntryName = targetModel.getMainTable();
		String subEntryName = targetModel.getSubTable();
		String mainTableName = entryTableMap.get(mainEntryName);
		String subTableName =entryTableMap.get(subEntryName);
		myBatisXMLModel.setMainTable(mainTableName);
		myBatisXMLModel.setSubTable(subTableName);
		
		String mainTableRegex = "^"+mainEntryName+".*";
		String subTableRegex = "^"+subEntryName+".*";
		
		String oriOnCondition = targetModel.getOnCondition();
		if(oriOnCondition.split("\\=").length<2){
			logger.info("ERROR about ONCONDITION in configuration files");
			return null;
		}		
		String left = oriOnCondition.split("\\=")[0];
		String right = oriOnCondition.split("\\=")[1];
		
		for(Entry<String,String>entry:attrColMap.entrySet()){
			String key = entry.getKey();
			String value = entry.getValue();
			if(left.endsWith(key)){
				left = left.replaceAll(key, value);
			}
			if(right.endsWith(key)){
				right = right.replaceAll(key, value);
			}
		}
		
		if(left.matches(mainTableRegex)){
			left = left.replaceAll(mainEntryName, mainTableName);
		}
		else if(left.matches(subTableRegex)){
			left = left.replaceAll(subEntryName, subTableName);
		}
		
		if(right.matches(mainTableRegex)){
			right = right.replaceAll(mainEntryName, mainTableName);
		}
		else if(right.matches(subTableRegex)){
			right = right.replaceAll(subEntryName, subTableName);
		}
		
		String sqlOnCondition = left+"="+right;
		myBatisXMLModel.setOnCondition(sqlOnCondition);
			
		String fixCol = "";
		//判断数据库类型
		String splitor = oracleAppender+"\'"+targetModel.getSplitor()+"\'"+oracleAppender;
		if(getDBType().equals("oracle"))
			splitor = oracleAppender+"\'"+targetModel.getSplitor()+"\'"+oracleAppender;
		else if (getDBType().equals("mssql"))
			splitor = mssqlAppender+"\'"+targetModel.getSplitor()+"\'"+mssqlAppender;
		
 		for(String tmp:targetModel.getSourceAttributes()){		
			if(tmp.matches(mainTableRegex)){
				tmp = tmp.replaceAll(mainEntryName, mainTableName);
			}
			else if(tmp.matches(subTableRegex)){
				tmp = tmp.replaceAll(subEntryName, subTableName);
			}
			for(Entry<String,String>entry:attrColMap.entrySet()){
				String key = entry.getKey();
				String value = entry.getValue();
				if(tmp.endsWith(key)){
					tmp = tmp.replaceAll(key, value);
					break;
				}
			}
			if(fixCol.equals(""))
				fixCol = tmp;
			else
				fixCol+=splitor+tmp;
		}
		String targetCol = targetModel.getTargetAttribute();
		for(Entry<String,String>entry:attrColMap.entrySet()){
			String key = entry.getKey();
			String value = entry.getValue();
			if(targetCol.endsWith(key)){
				targetCol = targetCol.replaceAll(key, value);
			}
		}
		fixCol+= " as "+targetCol;
		
		targetCol = targetModel.getTargetAttribute();
		Field [] fields = cls.getDeclaredFields();
		for(Field f:fields){
			String fName = f.getName();
			if(fName.equalsIgnoreCase(targetCol))
				continue;
			for(Entry<String,String>entry:attrColMap.entrySet()){
				String key = entry.getKey();
				String value = entry.getValue();
				if(fName.endsWith(key)){
					fName = fName.replaceAll(key, value);
				}
			}
			fixCol+=","+mainTableName+"."+fName;
		}
		
		myBatisXMLModel.setFixedColList(fixCol);
		
		return myBatisXMLModel;
	}
	
	
}
